package dao

import (
	"errors"
	"go.uber.org/zap"
	"log"
	"math/rand"
	"smart-health-platforms/config"
	"smart-health-platforms/pkg"
	"strconv"
	"time"
	"user_srv/model"
	"user_srv/user"
)

// 验证码发送
func SendSms(in *user.SendSmsRequest) (string, error) {
	//限制发送次数
	get := config.Rdb.Get(config.Ctx, "sms_count"+in.Mobile).Val()
	if get == "3" {
		return "", errors.New("短信一小时内只允许发送三次")
	}
	init := rand.Intn(9000) + 1000
	//aliyun := untils.AliSms{}
	//err := aliyun.AliYun(in.Mobile, strconv.Itoa(init))
	//if err != nil {
	//	return nil, errors.New("短信验证码发送失败")
	//}
	//存储到redis
	config.Rdb.Set(config.Ctx, "sms"+in.Mobile, init, time.Hour)
	config.Rdb.Incr(config.Ctx, "sms_count"+in.Mobile)
	config.Rdb.Expire(config.Ctx, "sms_count"+in.Mobile, time.Hour)

	pkg.Warn("短信验证码发送成功",
		zap.String("sms", strconv.Itoa(init)))
	return strconv.Itoa(init), nil
}

// 登录注册一体化
func InterGRation(in *user.InterGRationRequest) (*model.Users, error) {
	//接收参数
	var users model.Users
	users.Mobile = in.Mobile
	if err := users.GetUserInfoByMobile(in.Mobile); err != nil {
		return nil, errors.New("用户表手机号查找失败")
	}
	if users.Id == 0 {
		//判断验证码是否正确
		smsCode := config.Rdb.Get(config.Ctx, "sms"+in.Mobile).Val()
		if smsCode != in.SmsCode {
			pkg.Warn("验证输入错误")
			return nil, errors.New("验证码输入错误")
		}
		//注册用户
		users.Password = pkg.DoubleMd5(in.Password)
		users.PermissionsId = uint(in.PermissionsId)
		if err := users.Create(); err != nil {
			return nil, errors.New("用户注册失败")
		}
		pkg.Warn("用户注册成功",
			zap.Int("id", int(users.Id)),
			zap.String("mobile", users.Mobile),
		)
	}
	// 用户登录，判断密码是否正确
	if users.Password != pkg.DoubleMd5(in.Password) {
		pkg.Warn("密码输入错误")
		return nil, errors.New("密码输入错误")
	}
	pkg.Warn("用户登录成功",
		zap.Int("id", int(users.Id)),
	)

	//用户登录次数自增
	users.LoginCount++
	err := users.UpdateLoginCount(int(users.Id), int(users.LoginCount))
	if err != nil {
		return nil, errors.New("用户登录次数更新失败")
	}
	//查询是否解锁该勋章
	var achievement model.Achievement
	if users.LoginCount >= 1 || users.LoginCount < 2 {
		//首次登录解锁勋章
		achievement = model.Achievement{
			UserId:            users.Id,
			RuleId:            3,
			AchievementName:   "新人入坑",
			AchievementDesc:   "用户首次完成登录",
			AchievementImages: "121.png",
			IsLighted:         1, //已点亮
			LightedTime:       time.Now(),
			Status:            1, //启用
		}
		err := achievement.LightAchievement(int(achievement.Id))
		if err != nil {
			log.Println("解锁“新人入坑”勋章失败", err)
		} else {
			log.Println("解锁“新人入坑”勋章成功")
		}
	} else if users.LoginCount >= 7 {
		//解锁“累加登录七天”勋章
		achievement = model.Achievement{
			UserId:            users.Id,
			RuleId:            1,
			AchievementName:   "累计登录七天",
			AchievementDesc:   "用户完成登录七天任务",
			AchievementImages: "121.png",
			IsLighted:         1, //已点亮
			LightedTime:       time.Now(),
			Status:            1, //启用
		}
		err := achievement.LightAchievement(int(achievement.Id))
		if err != nil {
			log.Println("解锁“累计登录七天”勋章失败", err)
		} else {
			log.Println("解锁“累计登录七天”勋章成功")
		}
	}

	// 检查会员是否即将过期（7天内）
	var memberLevel model.MemberUserLevel
	memberLevel.UserId = int32(users.Id)
	if err := memberLevel.GetUserLevel(); err == nil {
		// 获取当前时间戳（秒）
		currentTime := uint64(time.Now().Unix())
		// 计算距离过期的时间（秒）
		expireDiff := memberLevel.ExpireDate - currentTime
		// 如果距离过期不足7天（7*24*60*60=604800秒）
		if expireDiff > 0 && expireDiff < 604800 {
			// 计算剩余天数
			daysRemaining := expireDiff / (24 * 60 * 60)
			pkg.Info("会员即将过期提醒",
				zap.Int("user_id", int(users.Id)),
				zap.Uint64("days_remaining", daysRemaining),
			)
			// 创建一条站内信通知
			message := &model.Message{
				SenderID:   0, // 0表示系统发送
				ReceiverID: int64(users.Id),
				Content:    "您的会员服务将在" + strconv.FormatUint(daysRemaining, 10) + "天后到期，请及时续费以保持会员权益。",
				Type:       1, // 1表示系统消息
				IsRead:     0,
			}
			if err = message.CreateMessage(); err != nil {
				pkg.Warn("创建会员过期通知失败", zap.Error(err))
			}
		}
	}

	return &users, nil
}

// 用户详情
func UserDetail(in *user.UserDetailRequest) (*model.Users, error) {
	var users model.Users
	if err := users.GetUserInfoByMobile(in.Mobile); err != nil {
		return nil, err
	}
	if users.UsersStatus == 2 {
		return nil, errors.New("该用户账号异常，禁止查看详情")
	}
	err := users.GetUserDetail(in.Mobile)
	pkg.Info("用户详情获取成功",
		zap.Int("id", int(users.Id)),
		zap.String("mobile", users.Mobile),
	)
	if err != nil {
		pkg.Warn("用户详情获取失败")
		return nil, errors.New("用户详情获取失败")
	}
	return &users, err
}

// 用户资料修改
func UserUpdate(in *user.UserUpdateRequest) (*model.Users, error) {
	var users model.Users
	if err := users.GetUserInfoById(int(in.Id)); err != nil {
		return nil, err
	}
	if users.UsersStatus == 2 {
		return nil, errors.New("该用户账号异常，请稍后重试")
	}
	users.Email = in.Email
	users.Age = uint(in.Age)
	users.Mobile = in.Mobile
	users.Gender = uint(in.Gender)
	users.ImageCur = in.ImageCur
	users.NickName = in.NickName
	err := users.UserUpdate(int(in.Id))
	pkg.Info("用户资料修改成功",
		zap.Int("id", int(users.Id)),
		zap.String("mobile", users.Mobile),
	)
	if err != nil {
		pkg.Warn("用户资料修改失败")
		return nil, errors.New("用户资料修改失败")
	}
	return &users, err
}

// 忘记密码
func ForgetPassword(in *user.ForgetPasswordRequest) (*model.Users, error) {
	var users model.Users
	if err := users.GetUserInfoById(int(in.Id)); err != nil {
		return nil, err
	}
	if users.UsersStatus == 2 {
		return nil, errors.New("该用户账号异常，无法修改密码")
	}
	users.Mobile = in.Mobile
	//判断验证码是否正确
	smsCode := config.Rdb.Get(config.Ctx, "sms"+in.Mobile).Val()
	if smsCode != in.SmsCode {
		pkg.Warn("验证输入错误")
		return nil, errors.New("验证码输入错误")
	}
	if users.Password == pkg.DoubleMd5(in.NewPassword) {
		pkg.Warn("原密码与新密码相同，请重新输入")
		return nil, errors.New("原密码与新密码相同，请重新输入")
	}
	users.Password = pkg.DoubleMd5(in.NewPassword)
	err := users.ForgetPassword(int(in.Id))
	pkg.Info("用户密码修改成功",
		zap.Int("id", int(users.Id)),
		zap.String("mobile", users.Mobile),
	)
	if err != nil {
		pkg.Warn("修改密码失败")
		return nil, errors.New("修改密码失败")
	}

	return &users, err
}

// 用户注销
func UserDelete(in *user.UserDeleteRequest) (*model.Users, error) {
	var users model.Users
	if err := users.GetUserInfoById(int(in.Id)); err != nil {
		return nil, err
	}
	if users.UsersStatus == 2 {
		return nil, errors.New("该用户账号异常，请稍后再试")
	}
	err := users.DeleteUser(int(in.Id))
	pkg.Info("用户账号注销成功")
	if err != nil {
		pkg.Warn("用户账号注销失败")
		return nil, errors.New("用户账号注销失败")
	}
	return &users, err
}

// 用户发表意见
func ExpressOpinions(in *user.ExpressOpinionsRequest) (*model.Opinion, error) {
	var opinion model.Opinion
	opinion.Opinion = in.Opinion
	opinion.UsersId = uint(in.UsersId)
	err := opinion.ExpressOpinions()
	pkg.Info("用户意见发表成功",
		zap.Int("id", int(opinion.Id)),
		zap.String("opinion", opinion.Opinion),
	)
	if err != nil {
		pkg.Warn("用户意见发表失败")
		return nil, errors.New("用户意见发表失败")
	}
	return &opinion, err
}
